package com.solution.admin.auth.security;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.solution.admin.auth.entity.ResourceEntity;
import com.solution.admin.auth.entity.RoleEntity;
import com.solution.admin.auth.entity.UserEntity;
import com.solution.admin.auth.service.ResourceService;
import com.solution.admin.auth.service.RoleService;
import com.solution.admin.auth.service.UserService;
import com.solution.admin.customer.entity.CompanyEntity;
import com.solution.admin.customer.entity.CustomerEntity;
import com.solution.admin.customer.service.CompanyService;
import com.solution.admin.customer.service.CustomerService;
import com.solution.admin.settings.entity.KeyMapEntity;
import com.solution.admin.settings.service.KeyMapService;
import com.solution.common.constants.PublicStatus;
import com.solution.common.entity.UserPrincipal;

/**
 * 系统安全认证实现类
 * @author ThinkGem
 * @version 2014-7-5
 */
@Service("systemAuthorizingRealm")
public class SolutionAuthorizingRealm extends AuthorizingRealm {
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private ResourceService resourceService;
	
	@Autowired
	private RoleService roleService;
	
	@Autowired
	private CustomerService customerService;
	
	@Autowired
	private CompanyService companyService;
	
	@Autowired
	private KeyMapService keyMapService;
	
	/**
	 * doGetAuthenticationInfo( AuthenticationToken token)理解为登陆验证。 认证回调函数, 登录时调用
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		String loginName = token.getUsername();
		String loginTerminalType = token.getLoginTerminal();
		Map<String, Object> param = new HashMap<String,Object>();
		param.put("loginName", loginName);
		
		UserEntity user = userService.getUserByName(param);
		
		if (user != null) {
			//获取加密密码
			String password = user.getPassword();
			// 获取加密盐
			String salt = user.getPasswordSalt();
			//微信绑定密码非明文，需要特殊处理
			if (PublicStatus.LOGIN_TERMINAL_TYPE.WX.getCode().equals(loginTerminalType)) {
				password = String.valueOf(new SimpleHash("MD5", token.getPassword(), salt.toString(), 1));
			}
			// 用户认证主体
			UserPrincipal principal = new UserPrincipal(user.getId(),
					user.getUserCode(), user.getUserName(), password,
					null, null, user.getDealerId(), user.getDealerName(),1);
			
			
			// WX\PC\管理后台端登录,都要查询客户信息相关，后续后台管理人员也要能登录前台查看商品（TODO）
			param.clear();
			// 登录用户名，手机号
			param.put("loginCode", user.getUserCode());
			List<CustomerEntity> customerList = customerService.listCustomer(param);
			if(customerList != null && customerList.size() > 0){
				CustomerEntity customer = customerList.get(0);
				// 客户信息 
				principal.setCustomer(customer);
				if(customer != null){
					// 单位信息
					CompanyEntity company = companyService.getCompanyById(customer.getCompanyId());
					principal.setCompany(company);
				}
			}
			
			param.clear();
			param.put("userId", principal.getId());
			List<RoleEntity> roleList = roleService.listRole(param);
			List<KeyMapEntity> salesmanRoleList = keyMapService.listKeyMap("salesmanRoleId");
			KeyMapEntity salesmanRole = salesmanRoleList.get(0);
			// 非销售人员
			String userAuthType = "2";
			if(roleList != null && roleList.size() > 0){
				for (RoleEntity role : roleList) {
					if(role.getId().toString().equals(salesmanRole.getKeyValue())){
						// 销售人员
						userAuthType = "1";
						break;
					}
				}
			}
			principal.setUserAuthType(userAuthType);
			
			return new SimpleAuthenticationInfo(principal,
					principal.getPassword(), ByteSource.Util.bytes(salt),
					getName());
		} else {
			return null;
		}
	}

	/**
	 * doGetAuthorizationInfo()方法可以理解为是权限验证 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		UserPrincipal principal = (UserPrincipal) getAvailablePrincipal(principals);
		String loginName = principal.getUserCode();
		// 查询用户信息
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("loginName", loginName);
		UserEntity user = userService.getUserByName(param);
		if (user != null) {
			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
			// 添加用户
			info.addStringPermission(user.getUserCode());
			// 添加用户角色信息
			param.clear();
			param.put("userId", principal.getId());
			List<ResourceEntity> resourceList = resourceService.listResource(param);
			// 查询用户的权限
			List<RoleEntity> roleList = roleService.listRole(param);
			// 添加用户权限
			if (roleList != null && roleList.size() > 0) {
				for (RoleEntity role : roleList) {
					if (role.getRoleCode() != null) {
						info.addStringPermission(role.getRoleCode());
					}
				}
			}
			// 添加用户资源
			if (resourceList != null && resourceList.size() > 0) {
				for (ResourceEntity resource : resourceList) {
					if (resource.getPermission() != null && !"".equals(resource.getPermission())) {
						info.addStringPermission(resource.getPermission());
					}
				}
			}
			return info;
		} else {
			return null;
		}
	}

	@Override
	protected void checkPermission(Permission permission, AuthorizationInfo info) {
		authorizationValidate(permission);
		super.checkPermission(permission, info);
	}

	@Override
	protected boolean[] isPermitted(List<Permission> permissions,
			AuthorizationInfo info) {
		if (permissions != null && !permissions.isEmpty()) {
			for (Permission permission : permissions) {
				authorizationValidate(permission);
			}
		}
		return super.isPermitted(permissions, info);
	}

	@Override
	public boolean isPermitted(PrincipalCollection principals,
			Permission permission) {
		authorizationValidate(permission);
		return super.isPermitted(principals, permission);
	}

	@Override
	protected boolean isPermittedAll(Collection<Permission> permissions,
			AuthorizationInfo info) {
		if (permissions != null && !permissions.isEmpty()) {
			for (Permission permission : permissions) {
				authorizationValidate(permission);
			}
		}
		return super.isPermittedAll(permissions, info);
	}

	/**
	 * 授权验证方法
	 * 
	 * @param permission
	 */
	private void authorizationValidate(Permission permission) {
		// 模块授权预留接口
	}

	/**
	 * 设定密码校验的Hash算法与迭代次数
	 */
	@PostConstruct
	public void initCredentialsMatcher() {
		HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("MD5");
		matcher.setHashIterations(1);
		setCredentialsMatcher(matcher);
	}
}
